package com.hq.zb.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hq.zb.dto.CodeRulesHeaderDto;
import com.hq.zb.exception.BizException;
import com.hq.zb.exception.BizExceptionEnum;
import com.hq.zb.mapper.CodeRulesHeaderMapper;
import com.hq.zb.model.Code;
import com.hq.zb.model.CodeLine;
import com.hq.zb.model.CodeRulesHeader;
import com.hq.zb.model.CodeRulesLine;
import com.hq.zb.service.ICodeRulesHeaderService;
import com.hq.zb.service.ICodeRulesLineService;
import com.hq.zb.vo.CodeRulesHeaderVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * 流水号规则ServiceImpl
 * @author huanghanrui
 * @since 2022-03-08
 */
@Service
@Transactional(rollbackFor= Exception.class)
public class CodeRulesHeaderServiceImpl extends ServiceImpl<CodeRulesHeaderMapper, CodeRulesHeader> implements ICodeRulesHeaderService {

    @Autowired
    private CodeRulesHeaderMapper codeRulesHeaderMapper;

    @Autowired
    private ICodeRulesLineService codeRulesLineService;

    @Override
    public void saveCodeRule(CodeRulesHeaderDto codeRulesHeaderDto) {
        CodeRulesHeader codeRulesHeader = new CodeRulesHeader();
        BeanUtil.copyProperties(codeRulesHeaderDto, codeRulesHeader);
        if (StringUtils.isNotBlank(codeRulesHeader.getRuleCode()) && StringUtils.isNotBlank(codeRulesHeader.getRuleName())) {
            codeRulesHeader.setEnableFlag(true);
            if (codeRulesHeader.getHeaderId() == null) {
                //新增
                codeRulesHeaderMapper.insert(codeRulesHeader);
            } else {
                //修改
                codeRulesHeaderMapper.updateById(codeRulesHeader);
            }
            //保存行表
            List<CodeRulesLine> codeRulesLines = codeRulesHeaderDto.getCodeRulesLines();
            if (codeRulesLines != null && !codeRulesLines.isEmpty()) {
                Wrapper<CodeRulesLine> wrapper = new EntityWrapper<>();
                wrapper.eq("rule_code", codeRulesHeader.getRuleCode());
                //删除旧行表，添加新的
                codeRulesLineService.delete(wrapper);
                for (CodeRulesLine codeRulesLine : codeRulesLines) {
                    codeRulesLine.setRuleCode(codeRulesHeader.getRuleCode());
                    //序列值为空的话默认是0
                    if ("SEQUENCE".equals(codeRulesLine.getFiledType()) && codeRulesLine.getStartValue() == null) {
                        codeRulesLine.setStartValue(0);
                        if (codeRulesLine.getSeqLength() == null) {
                            throw new BizException(BizExceptionEnum.DATA_NOT_NULL, "序列长度不允许为空.");
                        }
                    }
                    codeRulesLineService.insert(codeRulesLine);
                }
                //codeRulesLineService.insertBatch(codeRulesLines);
            }
        } else {
            throw new BizException(BizExceptionEnum.DATA_NOT_NULL, "流水号编码和流水号名称不允许为空.");
        }
    }

    @Override
    public String getCode(String ruleCode) {
        //查询流水号规则
        Wrapper<CodeRulesHeader> wrapper = new EntityWrapper<>();
        wrapper.eq("rule_code", ruleCode);
        wrapper.eq("delete_flag", false);
        List<CodeRulesHeader> codeRulesHeaderList =  this.selectList(wrapper);
        if (CollectionUtil.isEmpty(codeRulesHeaderList)) {
            //流水号规则不存在
            throw new BizException(BizExceptionEnum.DATA_NOT_EXIST, "流水号编码在系统中不存在.");
        } else {
            return this.getCode(codeRulesHeaderList);
        }
    }

    @Override
    public String getCode(String ruleCode, String ruleName, String constant, Integer seqLength) {
        //流水号规则编码必填
        if (StringUtils.isEmpty(ruleCode)) {
            throw new BizException(BizExceptionEnum.DATA_NOT_NULL, "流水号规则编码不允许为空");
        }
        if (seqLength == null || seqLength <= 0) {
            throw new BizException(BizExceptionEnum.DATA_NOT_NULL, "序列长度必须大于0");
        }
        //查询流水号规则
        Wrapper<CodeRulesHeader> wrapper = new EntityWrapper<>();
        wrapper.eq("rule_code", ruleCode);
        wrapper.eq("delete_flag", false);
        List<CodeRulesHeader> codeRulesHeaderList =  this.selectList(wrapper);
        if (CollectionUtil.isEmpty(codeRulesHeaderList)) {
            //生成一条编码规则
            CodeRulesHeaderDto codeRulesHeader = new CodeRulesHeaderDto();
            codeRulesHeader.setRuleCode(ruleCode);
            codeRulesHeader.setRuleName(ruleName);
            List<CodeRulesLine> codeRulesLines = new ArrayList<>();
            if (StringUtils.isNotEmpty(constant)) {
                CodeRulesLine codeRulesLine = new CodeRulesLine();
                codeRulesLine.setFiledType("CONSTANT");
                codeRulesLine.setFiledValue(constant);
                codeRulesLines.add(codeRulesLine);
            }
            CodeRulesLine rulesLine = new CodeRulesLine();
            rulesLine.setFiledType("SEQUENCE");
            rulesLine.setSeqLength(seqLength);
            rulesLine.setStartValue(0);
            rulesLine.setCurrentValue(0);
            codeRulesLines.add(rulesLine);
            codeRulesHeader.setCodeRulesLines(codeRulesLines);
            this.saveCodeRule(codeRulesHeader);
            wrapper.eq("rule_code", ruleCode);
            wrapper.eq("delete_flag", false);
            codeRulesHeaderList =  this.selectList(wrapper);
        }
        return this.getCode(codeRulesHeaderList);
    }

    @Override
    public Page<CodeRulesHeaderVo> queryCodeRules(Page<CodeRulesHeaderVo> page, Wrapper<CodeRulesHeaderVo> wrapper) {
        page.setRecords(codeRulesHeaderMapper.queryCodeRules(page, wrapper));
        return page;
    }

    @Override
    public void deleteCodeRulesHeader(List<CodeRulesHeader> codeRulesHeaders) {
        if (CollectionUtil.isNotEmpty(codeRulesHeaders)) {
            for (CodeRulesHeader codeRulesHeader : codeRulesHeaders) {
                codeRulesHeader.setDeleteFlag(true);
                this.updateById(codeRulesHeader);
                Wrapper<CodeRulesLine> codeLineWrapper = new EntityWrapper<>();
                codeLineWrapper.eq("rule_code", codeRulesHeader.getRuleCode());
                List<CodeRulesLine> codeLines = codeRulesLineService.selectList(codeLineWrapper);
                if (CollectionUtil.isNotEmpty(codeLines)) {
                    for (CodeRulesLine codeRulesLine : codeLines) {
                        codeRulesLine.setDeleteFlag(true);
                        codeRulesLineService.updateById(codeRulesLine);
                    }
                }
            }
        }
    }

    @Override
    public void deletecodeRulesLine(List<CodeRulesLine> codeRulesLines) {
        if (CollectionUtil.isNotEmpty(codeRulesLines)) {
            for (CodeRulesLine codeRulesLine : codeRulesLines) {
                codeRulesLine.setDeleteFlag(true);
                codeRulesLineService.updateById(codeRulesLine);
            }
        }
    }

    private String getCode(List<CodeRulesHeader> codeRulesHeaderList) {
        //查询流水号配置行表
        Wrapper<CodeRulesLine> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("rule_code", codeRulesHeaderList.get(0).getRuleCode());
        entityWrapper.orderBy("field_sequence asc");
        List<CodeRulesLine> codeRulesLines = codeRulesLineService.selectList(entityWrapper);
        if (CollectionUtil.isNotEmpty(codeRulesLines)) {
            StringBuffer stringBuffer = new StringBuffer();
            CodeRulesLine rulesLine = new CodeRulesLine();
            for (CodeRulesLine codeRulesLineDto : codeRulesLines) {
                if ("CONSTANT".equals(codeRulesLineDto.getFiledType()) && StringUtils.isNotEmpty(codeRulesLineDto.getFiledValue())) {
                    stringBuffer.append(codeRulesLineDto.getFiledValue());
                } else if ("DATE".equals(codeRulesLineDto.getFiledType())) {
                    String date = DateUtil.format(new Date(), codeRulesLineDto.getDateMask());
                    stringBuffer.append(date);
                } else if ("SEQUENCE".equals(codeRulesLineDto.getFiledType())){
                    Integer currentValue = codeRulesLineDto.getCurrentValue();
                    //重置频率
                    if ("DAY".equals(codeRulesLineDto.getResetFrequency())) {
                        if (codeRulesLineDto.getResetDate() != null && !DateUtil.formatDate(codeRulesLineDto.getResetDate()).equals(DateUtil.formatDate(new Date()))) {
                            currentValue = null;
                        }
                    }
                    if ("MONTH".equals(codeRulesLineDto.getResetFrequency())) {
                        if (codeRulesLineDto.getResetDate() != null && !DateUtil.format(codeRulesLineDto.getResetDate(), "YYYY-MM").equals(DateUtil.format(new Date(), "YYYY-MM"))) {
                            currentValue = null;
                        }
                    }
                    if ("YEAR".equals(codeRulesLineDto.getResetFrequency())) {
                        if (codeRulesLineDto.getResetDate() != null && !DateUtil.format(codeRulesLineDto.getResetDate(), "YYYY").equals(DateUtil.format(new Date(), "YYYY"))) {
                            currentValue = null;
                        }
                    }
                    if (currentValue == null) {
                        currentValue = 0;
                    } else {
                        currentValue +=1;
                    }
                    String seq = String.format("%0" + codeRulesLineDto.getSeqLength()+ "d",currentValue);
                    stringBuffer.append(seq);
                    codeRulesLineDto.setCurrentValue(currentValue);
                    BeanUtil.copyProperties(codeRulesLineDto, rulesLine);
                }
            }
            //更新
            codeRulesLineService.updateById(rulesLine);
            return stringBuffer.toString();
        } else {
            throw new BizException(BizExceptionEnum.DATA_NOT_EXIST, "流水号编码规则行表在系统中不存在.");
        }
    }
}
